package com.zzti.pay.alipay;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayDataDataserviceBillDownloadurlQueryRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.zzti.pay.service.MyBusiness;
import com.zzti.pay.service.OwnBusiness;
import com.zzti.pay.utils.JsonUtils;

@Component
public class AlipayWap {
	private static final Logger log = LoggerFactory.getLogger(AlipayWap.class);

	/**
	 * 返回实例化的客户端
	 *
	 * @return AlipayClient对象
	 */
	private AlipayClient getAlipayClient() {
		// 实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(AlipayConf.URL, AlipayConf.APPID,
				AlipayConf.RSA_PRIVATE_KEY, AlipayConf.FORMAT, AlipayConf.CHARSET, AlipayConf.ALIPAY_PUBLIC_KEY,
				AlipayConf.SIGN_TYPE);
		return alipayClient;
	}

	/**
	 * 支付宝支付接口
	 * 
	 * @param httpResponse
	 *            响应对象
	 * @param subject
	 *            订单标题
	 * @param totalAmount
	 *            订单总金额，单位为元，精确到小数点后两位，取值范围[0.01,100000000]
	 * @param tradeNo
	 *            商户订单号，需要保证不重复
	 */
	public void toPay(HttpServletResponse httpResponse, String subject, String total_amount, String out_trade_no) {
		AlipayClient alipayClient = getAlipayClient();
		// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
		// 在公共参数中设置回跳和通知地址
		request.setReturnUrl(AlipayConf.return_url);
		request.setNotifyUrl(AlipayConf.notify_url);
		Map<String, Object> map = new HashMap<>();
		map.put("out_trade_no", out_trade_no); // 商户订单号，需要保证不重复
		map.put("total_amount", total_amount); // 订单金额
		map.put("subject", subject); // 订单标题
		map.put("product_code", "QUICK_WAP_PAY");
		log.info(JsonUtils.objectToJson(map));
		request.setBizContent(JsonUtils.objectToJson(map)); // 填充业务参数
		String form = "";
		try {
			// 这里和普通的接口调用不同，使用的是sdkExecute
			AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
			form = response.getBody();
			log.info("打印请求支付返回的数据", form);
			System.out.println(form);// 就是orderString 可以直接给客户端请求，无需再做处理。
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		httpResponse.setContentType("text/html;charset=" + AlipayConf.CHARSET);
		try {
			httpResponse.getWriter().write(form);
			httpResponse.getWriter().flush();
			httpResponse.getWriter().close();
		} catch (IOException e) {
			log.error("支付成功回传页面时出问题了");
			e.printStackTrace();
		} // 直接将完整的表单html输出到页面
	}

	/**
	 * 支付宝异步通知验签
	 *
	 * @param request
	 *            请求体
	 * @return 通知支付宝成功还是失败
	 */
	public String AsynchronousNotifyCheck(HttpServletRequest request) {
		// 支付宝支付结束回调接口
		String result = AlipayConf.FAILURE;
		// 将异步通知中收到的所有参数都存放到map中
		Map<String, String> paramsMap = new HashMap<String, String>();
		// 获取支付宝POST过来反馈信息
		Map<String, String[]> requestParams = request.getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			paramsMap.put(name, valueStr);
		}
		log.info(JsonUtils.objectToJson(paramsMap));
		log.info("订单号为：" + paramsMap.get("out_trade_no"));
		boolean signVerified;
		try {
			// 调用SDK验证签名
			signVerified = AlipaySignature.rsaCheckV1(paramsMap, AlipayConf.ALIPAY_PUBLIC_KEY, AlipayConf.CHARSET,
					AlipayConf.SIGN_TYPE);
			if (!signVerified) {
				// 验签失败则记录异常日志，并在response中返回failure.
				log.error("调用SDK验证签名失败");
				return result;
			}
			String app_id = paramsMap.get("app_id"); // 商户的app_id
			if (!AlipayConf.APPID.equals(app_id)) {
				// 验签失败则记录异常日志，并在response中返回failure.
				log.error("调用APPID验证签名失败");
				return result;
			}
			// 调用service 实现自己的方法
			OwnBusiness own = new MyBusiness();
			// 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
			boolean myResult = own.myBusiness(paramsMap, "alipay");
			if (myResult) {
				result = AlipayConf.SUCCESS;
			}

		} catch (AlipayApiException e) {
			log.error("异步通知出异常了");
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 交易查询接口
	 * 
	 * @param out_trade_no
	 *            支付时传入的商户订单号，与trade_no必填一个
	 * @param trade_no
	 *            支付时返回的支付宝交易号，与out_trade_no必填一个
	 * @return trade_no 支付宝28位交易号 out_trade_no 支付时传入的商户订单号 trade_status 交易当前状态
	 */
	public String tradeQuery(String out_trade_no, String trade_no) {
		log.info("开始订单查询");
		AlipayClient alipayClient = getAlipayClient();
		AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); // 创建API对应的request类
		Map<String, String> map = new HashMap<>();
		if ((out_trade_no != null) && (!"".equals(out_trade_no))) {
			map.put("out_trade_no", out_trade_no);
		}
		if ((trade_no != null) && (!"".equals(trade_no))) {
			map.put("trade_no", trade_no);
		}
		request.setBizContent(JsonUtils.objectToJson(map));// 设置业务参数
		AlipayTradeQueryResponse response;
		try {
			// 通过alipayClient调用API，获得对应的response类
			response = alipayClient.execute(request);
			log.info("支付宝订单详情：", response.getBody());
			return response.getBody();
		} catch (AlipayApiException e) {
			log.error("支付宝订单查询出异常了");
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 交易退款接口alipay.trade.refund
	 *
	 * @param out_trade_no
	 *            支付时传入的商户订单号，与trade_no必填一个
	 * @param trade_no
	 *            支付时返回的支付宝交易号，与out_trade_no必填一个
	 * @param out_request_no
	 *            本次退款请求流水号，部分退款时必传
	 * @param refund_amount
	 *            本次退款金额
	 * @return refund_fee 该笔交易已退款的总金额
	 */
	public String tradeRefund(String out_trade_no, String trade_no, String out_request_no, String refund_amount) {
		AlipayClient alipayClient = getAlipayClient();
		// 创建API对应的request类
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		Map<String, String> map = new HashMap<>();
		if ((out_trade_no != null) && (!"".equals(out_trade_no))) {
			map.put("out_trade_no", out_trade_no);
		}
		if ((trade_no != null) && (!"".equals(trade_no))) {
			map.put("trade_no", trade_no);
		}
		map.put("out_request_no", out_request_no);
		map.put("refund_amount", refund_amount);
		request.setBizContent(JsonUtils.objectToJson(map)); // 设置业务参数
		AlipayTradeRefundResponse response;
		try {
			// 通过alipayClient调用API，获得对应的response类
			// 根据response中的结果继续业务逻辑处理
			response = alipayClient.execute(request);
			log.info("支付宝交易退款详情：", response.getBody());
			return response.getBody();
		} catch (AlipayApiException e) {
			e.printStackTrace();
			log.error("支付宝交易退款出异常了:", e.toString());
		}
		return "";
	}

	/**
	 * 查询对账单下载地址
	 * 
	 * @param bill_type
	 *            固定传入 "trade"
	 * @param bill_date
	 *            需要下载的账单日期，最晚是当期日期的前一天(格式为：2016-04-05)
	 * @return 账单文件下载地址，30秒有效
	 */
	public String queryBillDownloadurl(String bill_type, String bill_date) {
		AlipayClient alipayClient = getAlipayClient();
		AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();// 创建API对应的request类
		Map<String, String> map = new HashMap<>();
		map.put("bill_type", bill_type);
		map.put("bill_date", bill_date);
		request.setBizContent(JsonUtils.objectToJson(map)); // 设置业务参数
		AlipayDataDataserviceBillDownloadurlQueryResponse response;
		try {
			response = alipayClient.execute(request);
			log.info("支付宝对账单下载地址", response.getBody());
			// bill_download_url
			return (String) JsonUtils.jsonToMap(JsonUtils.objectToJson(response.getBody())).get("bill_download_url");
			// return response.getBody();
			// 根据response中的结果继续业务逻辑处理
		} catch (AlipayApiException e) {
			log.error("查询支付宝对账单下载地址出异常了，异常原因：", e.toString());
			e.printStackTrace();
		}
		return "";
	}
}
